/*
 * $Id:
 *
 * Copyright (C) 2011 Refiner Inc.
 * All right reserved
 *
 *============================================================
 * +rVPN Stack : AppIF (Application Interface)
 *============================================================
 * abstract: AppIFでのメッセージ処理共通関数
 * author  : MURATA
 * history :
 *
 */

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include "rvs_appif.h"
#include "rvs_socket.h"
#include "rvs_msg.h"

#ifdef NO_THREADS
int rvs_errno = 0;
#else
typedef struct _rvs_thlocal
{
    int rt_errno;    /* エラー番号 */
    /* Others - 必要なら他のスレッドローカル変数を追加 */
} rvs_thlocal_t;

static pthread_once_t once_control = PTHREAD_ONCE_INIT;
static pthread_key_t rvs_thkey;

static void rvs_thl_destroy(void* var)
{
    if (var) free(var);
}

static void rvs_thl_init(void)
{
    if (pthread_key_create(&rvs_thkey, &rvs_thl_destroy) < 0) {
        LOGE("%s: pthread_key_create() failed.. %s\n",
                __FUNCTION__, strerror(errno));
        return;
    }
}

int __rvs_error(void)
{
    rvs_thlocal_t *thl;

    /* 初期化 */
    pthread_once(&once_control, &rvs_thl_init);

    /* スレッドローカル取得 */
    thl = (rvs_thlocal_t*)pthread_getspecific(rvs_thkey);

    if (thl == NULL) { return 0; }
    return thl->rt_errno;
}

void  rvs_set_errno(int err)
{
    rvs_thlocal_t *thl;

    /* 初期化 */
    pthread_once(&once_control, &rvs_thl_init);

    /* スレッドローカル取得 */
    thl = (rvs_thlocal_t*)pthread_getspecific(rvs_thkey);

    /* なければ確保して登録 */
    if (thl == NULL) {
        thl = (rvs_thlocal_t*)malloc(sizeof(rvs_thlocal_t));
        if (thl == NULL) {
            LOGE("%s: malloc() failed.. %s\n",
                    __FUNCTION__, strerror(errno));
            return;
        }
        memset (thl, 0, sizeof(rvs_thlocal_t));
        pthread_setspecific(rvs_thkey, (const void*)thl);
    }

    thl->rt_errno = err;
}
#endif /* NO_THREADS */

#define RCVBUFLEN	        2048

#define SENDTOBASE \
        (sizeof(rvs_api_int_t)*2+sizeof(rvs_api_av4_t)+sizeof(rvs_api_ubuf_t))
#define RECVFROMBASE \
        (sizeof(rvs_api_av4_t)+sizeof(rvs_api_ubuf_t))
#define SENDBASE \
        (sizeof(rvs_api_int_t)*2+sizeof(rvs_api_ubuf_t))
#define RECVBASE \
        (sizeof(rvs_api_ubuf_t))

static rvs_api_int_t* get_int_param(rvs_api_tlv_t* tlv)
{
    rvs_api_int_t* intp = (rvs_api_int_t*)tlv;
    if (tlv->Length < sizeof(uint32_t)) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }

    intp->Integer = ntohl(intp->Integer);
    return intp;
}

static rvs_api_int_t* set_int_param(rvs_api_tlv_t* tlv)
{
    rvs_api_int_t* intp = (rvs_api_int_t*)tlv;
    if (tlv->Length < sizeof(uint32_t)) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }

    intp->Integer = htonl(intp->Integer);
    return intp;
}

static rvs_api_sev_t* get_sev_param(rvs_api_tlv_t* tlv)
{
    rvs_api_sev_t* sev = (rvs_api_sev_t*)tlv;
    if (tlv->Length < sizeof(uint32_t)*2) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    sev->rSocket = ntohl(sev->rSocket);
    sev->ReqEvents = ntohs(sev->ReqEvents);
    sev->Events = ntohs(sev->Events);
    return sev;
}

static rvs_api_sev_t* set_sev_param(rvs_api_tlv_t* tlv)
{
    rvs_api_sev_t* sev = (rvs_api_sev_t*)tlv;
    if (tlv->Length < sizeof(uint32_t)*2) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    sev->rSocket = htonl(sev->rSocket);
    sev->ReqEvents = htons(sev->ReqEvents);
    sev->Events = htons(sev->Events);
    return sev;
}

static rvs_api_av4_t* get_av4_param(rvs_api_tlv_t* tlv)
{
    rvs_api_av4_t* av4 = (rvs_api_av4_t*)tlv;
    if (tlv->Length < sizeof(uint32_t)*2) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    return av4;
}

static rvs_api_av4_t* set_av4_param(rvs_api_tlv_t* tlv)
{
    rvs_api_av4_t* av4 = (rvs_api_av4_t*)tlv;
    if (tlv->Length < sizeof(uint32_t)*2) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    return av4;
}

static rvs_api_av6_t* get_av6_param(rvs_api_tlv_t* tlv)
{
    rvs_api_av6_t* av6 = (rvs_api_av6_t*)tlv;
    if (tlv->Length < sizeof(uint32_t)*3+sizeof(struct in6_addr)) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    return av6;
}

static rvs_api_av6_t* set_av6_param(rvs_api_tlv_t* tlv)
{
    rvs_api_av6_t* av6 = (rvs_api_av6_t*)tlv;
    if (tlv->Length < sizeof(uint32_t)*3+sizeof(struct in6_addr)) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    return av6;
}

static rvs_api_ai_t* get_ai_param(rvs_api_tlv_t* tlv)
{
    rvs_api_tlv_t* av;
    rvs_api_ai_t* ainfo = (rvs_api_ai_t*)tlv;
    int left = tlv->Length;

    if (left < sizeof(uint32_t)*4) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    ainfo->Flags = ntohl(ainfo->Flags);
    ainfo->Family = ntohl(ainfo->Family);
    ainfo->SockType = ntohl(ainfo->SockType);
    ainfo->Protocol = ntohl(ainfo->Protocol);
    left -= sizeof(uint32_t)*4;

    if (left < sizeof(uint32_t)) {
        rvs_set_errno(EINVAL);
        return NULL;
    }
    left -= sizeof(uint32_t);

    av = (rvs_api_tlv_t*)&ainfo->Address;
    av->Type = ntohs(av->Type);
    av->Length = ntohs(av->Length);

    if (left < av->Length) {
        rvs_set_errno(EINVAL);
        return NULL;
    }

    if (ainfo->Family == AF_INET) {
        if (get_av4_param(av) == NULL) return NULL;
    } else {
        if (get_av6_param(av) == NULL) return NULL;
    }
    return ainfo;
}

static rvs_api_ai_t* set_ai_param(rvs_api_tlv_t* tlv)
{
    rvs_api_tlv_t* av;
    rvs_api_ai_t* ainfo = (rvs_api_ai_t*)tlv;
    int left = tlv->Length;

    if (left < sizeof(uint32_t)*4) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    ainfo->Flags = htonl(ainfo->Flags);
    ainfo->Family = htonl(ainfo->Family);
    ainfo->SockType = htonl(ainfo->SockType);
    ainfo->Protocol = htonl(ainfo->Protocol);
    left -= sizeof(uint32_t)*4;

    if (left < sizeof(uint32_t)) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    left -= sizeof(uint32_t);

    av = (rvs_api_tlv_t*)&ainfo->Address;
    av->Type = htons(av->Type);
    av->Length = htons(av->Length);

    if (left < av->Length) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }

    if (ainfo->Family == AF_INET) {
        if (set_av4_param(av) == NULL) return NULL;
    } else {
        if (set_av6_param(av) == NULL) return NULL;
    }
    return ainfo;
}

static rvs_api_ail_t* get_ail_param(rvs_api_tlv_t* tlv)
{
    int left = tlv->Length;
    rvs_api_tlv_t* cur;

    rvs_api_ail_t* alist = (rvs_api_ail_t*)tlv;
    cur = (rvs_api_tlv_t*)alist->AddrInfo;

    while (left > 0) {
        int alen;

        if (left > sizeof(uint32_t)) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }
        cur->Type = ntohs(cur->Type);
        cur->Length = ntohs(cur->Length);
        left -= sizeof(uint32_t);

        if (left < cur->Length) {
            rvs_set_errno(EINVAL);
            return NULL;
        }

        /* AddrInfo */
        if (get_ai_param(cur) == NULL) return NULL;
        alen = cur->Length;
        if (alen % sizeof(uint32_t)) {
            alen += (sizeof(uint32_t)-(alen%sizeof(uint32_t)));
        }
        cur = (rvs_api_tlv_t*)((char*)cur->Value + alen);
        left -= alen;
    }
    
    return alist;
}

static rvs_api_ail_t* set_ail_param(rvs_api_tlv_t* tlv)
{
    int left = tlv->Length;
    rvs_api_tlv_t* cur;

    rvs_api_ail_t* alist = (rvs_api_ail_t*)tlv;
    cur = (rvs_api_tlv_t*)alist->AddrInfo;

    while (left > 0) {
        int alen;

        if (left > sizeof(uint32_t)) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }
 //       cur->Type = htons(cur->Type);
 //       cur->Length = htons(cur->Length);
        left -= sizeof(uint32_t);

        if (left < cur->Length) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }

        /* AddrInfo */
        if (set_ai_param(cur) == NULL) return NULL;
        alen = cur->Length;
        if (alen % sizeof(uint32_t)) {
            alen += (sizeof(uint32_t)-(alen%sizeof(uint32_t)));
        }

        cur->Type = htons(cur->Type);
        cur->Length = htons(cur->Length);

        cur = (rvs_api_tlv_t*)((char*)cur->Value + alen);
        left -= alen;
    }

    return alist;
}

static rvs_api_sel_t* get_sel_param(rvs_api_tlv_t* tlv)
{
    int left = tlv->Length;
    rvs_api_tlv_t* cur;

    rvs_api_sel_t* selist = (rvs_api_sel_t*)tlv;
    cur = (rvs_api_tlv_t*)selist->SockEvent;

    while (left > 0) {
        int alen;

        if (left < sizeof(uint32_t)) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }
        cur->Type = ntohs(cur->Type);
        cur->Length = ntohs(cur->Length);
        left -= sizeof(uint32_t);

        if (left < cur->Length) {
            rvs_set_errno(EINVAL);
            return NULL;
        }

        /* SockEvent */
        if (get_sev_param(cur) == NULL) return NULL;
        alen = cur->Length;
        if (alen % sizeof(uint32_t)) {
            alen += (sizeof(uint32_t)-(alen%sizeof(uint32_t)));
        }
        cur = (rvs_api_tlv_t*)((char*)cur->Value + alen);
        left -= alen;
    }

    return selist;
}

static rvs_api_sel_t* set_sel_param(rvs_api_tlv_t* tlv)
{
    int left = tlv->Length;
    rvs_api_tlv_t* cur;

    rvs_api_sel_t* selist = (rvs_api_sel_t*)tlv;
    cur = (rvs_api_tlv_t*)selist->SockEvent;

    while (left > 0) {
        int alen;

        if (left < sizeof(uint32_t)) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }
//        cur->Type = htons(cur->Type);
//        cur->Length = htons(cur->Length);
        left -= sizeof(uint32_t);

        if (left < cur->Length) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }

        /* SockEvent */
        if (set_sev_param(cur) == NULL) return NULL;
        alen = cur->Length;
        if (alen % sizeof(uint32_t)) {
            alen += (sizeof(uint32_t)-(alen%sizeof(uint32_t)));
        }

        cur->Type = htons(cur->Type);
        cur->Length = htons(cur->Length);

        cur = (rvs_api_tlv_t*)((char*)cur->Value + alen);
        left -= alen;
    }

    return selist;
}

static rvs_api_status_t* get_status_param(rvs_api_tlv_t* tlv)
{
    rvs_api_status_t* stat = (rvs_api_status_t*)tlv;
    int left = tlv->Length;
    rvs_api_tlv_t* cur;
    int i;

    if (left < sizeof(uint16_t)*2) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    stat->VPNStat = ntohs(stat->VPNStat);
    stat->P2PCount = ntohs(stat->P2PCount);
    left -= sizeof(uint16_t)*2;

    cur = (rvs_api_tlv_t*)stat->Remote;
    for (i=0; i<stat->P2PCount; i++) {
        int alen;

        if (left < sizeof(rvs_api_tlv_t)) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }
        
        cur->Type = ntohs(cur->Type);
        cur->Length = ntohs(cur->Length);
        alen = cur->Length;
        if (alen % sizeof(uint32_t)) {
            alen += (sizeof(uint32_t) - (cur->Length % sizeof(uint32_t)));
        }
        if (left < alen) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }

        cur = (rvs_api_tlv_t*)((char*)cur->Value + alen);
        left -= alen;
    }

    return stat;
}

static rvs_api_status_t* set_status_param(rvs_api_tlv_t* tlv)
{
    rvs_api_status_t* stat = (rvs_api_status_t*)tlv;
    int left = tlv->Length;
    rvs_api_tlv_t* cur;
    int i;

    if (left < sizeof(uint16_t)*2) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }

    cur = (rvs_api_tlv_t*)stat->Remote;
    left -= sizeof(uint16_t)*2;

    for (i=0; i<stat->P2PCount; i++) {
        int alen;

        if (left < sizeof(rvs_api_tlv_t)) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }

        alen = cur->Length;
        if (alen % sizeof(uint32_t)) {
            alen += (sizeof(uint32_t) - (cur->Length % sizeof(uint32_t)));
        }
        left -= sizeof(rvs_api_tlv_t);

        if (left < alen) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }

        cur->Type = htons(cur->Type);
        cur->Length = htons(cur->Length);

        cur = (rvs_api_tlv_t*)((char*)cur->Value + alen);
        left -= alen;
    }

    stat->VPNStat = htons(stat->VPNStat);
    stat->P2PCount = htons(stat->P2PCount);

    return stat;
}


static rvs_api_error_t* get_error_param(rvs_api_tlv_t* tlv)
{
    rvs_api_error_t* errp = (rvs_api_error_t*)tlv;
    int left = tlv->Length;

    if (left < (sizeof(uint32_t)+sizeof(errp->ErrCode))) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }
    errp->RequestType = ntohs(errp->RequestType);
    errp->ReasonType = ntohs(errp->ReasonType);
    if (errp->ReasonType == RVS_REASON_2) {
        errp->ErrCode.RCode2[0] = ntohs(errp->ErrCode.RCode2[0]);
        errp->ErrCode.RCode2[1] = ntohs(errp->ErrCode.RCode2[1]);
    }
    left -= (sizeof(uint32_t)+sizeof(errp->ErrCode));

    if (left > 0) {
        rvs_api_tlv_t* cur = (rvs_api_tlv_t*)errp->Remote;
        if (left < sizeof(uint32_t)) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }

        cur->Type = ntohs(cur->Type);
        cur->Length = ntohs(cur->Length);
        left -= sizeof(uint32_t);

        if (left < cur->Length) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }
    }

    return errp;
}

static rvs_api_error_t* set_error_param(rvs_api_tlv_t* tlv)
{
    rvs_api_error_t* errp = (rvs_api_error_t*)tlv;
    int left = tlv->Length;

    if (left < (sizeof(uint32_t)+sizeof(errp->ErrCode))) {
        LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
        rvs_set_errno(EINVAL);
        return NULL;
    }

    if (errp->ReasonType == RVS_REASON_2) {
        errp->ErrCode.RCode2[0] = htons(errp->ErrCode.RCode2[0]);
        errp->ErrCode.RCode2[1] = htons(errp->ErrCode.RCode2[1]);
    }
    errp->RequestType = htons(errp->RequestType);
    errp->ReasonType = htons(errp->ReasonType);
    left -= (sizeof(uint32_t)+sizeof(errp->ErrCode));

    if (left > 0) {
        rvs_api_tlv_t* cur = (rvs_api_tlv_t*)errp->Remote;
        if (left < sizeof(uint32_t)) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }

        left -= sizeof(uint32_t);
        if (left < cur->Length) {
            LOGE("%s: Internal Error(Length=%d)\n", __FUNCTION__, tlv->Length);
            rvs_set_errno(EINVAL);
            return NULL;
        }

        cur->Type = htons(cur->Type);
        cur->Length = htons(cur->Length);
    }

    return errp;
}


/*
 * rvs_free_msg - 受信メッセージ構造体の解放
 *
 *     msg  : メッセージ構造体格納バッファ
 */
void rvs_free_msg(rvs_api_msg_t* msg)
{
    if (msg->baloc) {
        rvs_free(msg->header);
        msg->baloc = 0;
    }
    if (msg->aloc) {
       rvs_free(msg);
    }
}

#define SKIP_BUF_LEN  2048
    static char skipbuf[SKIP_BUF_LEN];
inline void readskip(int sock, int length)
{
    while (length > 0) {
        read (sock, skipbuf, (length>SKIP_BUF_LEN)?SKIP_BUF_LEN:length);
        length -= SKIP_BUF_LEN;
    }
}

/*
 * rvs_recv_msg - メッセージ受信
 *
 *     sock : 受信ソケット(SOCK_STREAM型であること)
 *     msg  : メッセージ構造体格納バッファ
 *            (NULLなら内部でヒープより確保)
 *     rbuf : 受信バッファ(NULLなら内部でヒープより確保)
 *     rbuflem : 受信バッファサイズ
 *     getbuf : Data用ユーザバッファ取得用関数
 *     param : getbufに渡す引数
 *   戻り値
 *     受信メッセージ構造体のアドレス(NULLの場合はエラー)
 *     rvs_errnoにエラー番号を設定する。rvs_errno = RVSA_EAGAIN
 *     のときは、次の受信イベントでリトライする。
 */
rvs_api_msg_t* rvs_recv_msg (int sock, rvs_api_msg_t* msg,
           int msgcode, int seqno,
           char* rbuf, int rbuflen, ubuf_func_t getbuf, void* param)
{
    int rcvlen=0, len;
    rvs_api_hdr_t hdr;
    char* cur;
    int plen, total;
    struct timeval tv, *tvp;

    rvs_set_errno(0);

    /* パラメータチェック */
    if (rbuf && (rbuflen < sizeof(rvs_api_hdr_t))) {
        LOGE("%s: buffer length is too short(%d)\n", __FUNCTION__, rbuflen);
        rvs_set_errno(EINVAL);
        return NULL;
    }
 
    /* メッセージ構造体設定 */
    if (msg == NULL) {
        msg = rvs_malloc(sizeof(rvs_api_msg_t));
        if (msg == NULL) {
            LOGE("%s: cannot allocate message buffer\n", __FUNCTION__);
            rvs_set_errno(ENOMEM);
            return NULL;
        }
        /* 初期化 */
        memset ( msg, 0, sizeof(rvs_api_msg_t) );
        msg->aloc = 1;
    } else {
        /* 初期化 */
        memset ( msg, 0, sizeof(rvs_api_msg_t) );
    }

    /* status_checkは本来待ちが発生しないが、下位のモジュールから
     * 返らなくなることを考慮して、タイムアウトを設定する
     * タイムアウトが発生した場合は、上位に通知し、上位で何らかの
     * 処置を行う */
    if (msgcode == RAPI_M_STATUSCHECK_RES) {
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        tvp = &tv;
    } else {
        tvp = NULL;
    }

    while (1) {
        int ret;
        fd_set readfds;

        FD_ZERO(&readfds);
        FD_SET(sock, &readfds);
        ret = select(sock+1, &readfds, NULL, NULL, tvp);

        /* タイムアウトが発生した場合は制御を戻す */
        if (ret == 0)
        {
            rvs_set_errno(EAGAIN);
            LOGE("%s: select timeout\n", __FUNCTION__);
            return NULL;
        }
        if (ret < 0)
        {
            rvs_set_errno(errno);
            LOGE("%s: select error: %s\n", __FUNCTION__, strerror(errno));
            return NULL;
        }

        /* Magic Codeの読み込み */
        if ((len = read(sock, (char*)&hdr.magic, sizeof(uint32_t))) < 0) {
            rvs_set_errno(errno);
            LOGE("%s: read magic code : %s\n", __FUNCTION__, strerror(errno));
            return NULL;
        }
        if ( len < sizeof(uint32_t)) {
            rvs_set_errno(RVSA_EOF);
            LOGE("%s: read(api sock) : End of File.\n", __FUNCTION__);
            return NULL;
        }
        if (hdr.magic != RVSA_MAGIC) {
            LOGD("%s: not magic code(0x%08x)\n", __FUNCTION__, hdr.magic);
            continue;
        }
        rcvlen = len;

        /* ヘッダの読み込み */
        len = read(sock, (char*)&hdr.msgcode, sizeof(hdr)-sizeof(uint32_t));
        if (len < (sizeof(hdr)-sizeof(uint32_t))) {
            rvs_set_errno(errno);
            LOGE("%s: read header : %s\n", __FUNCTION__, strerror(errno));
            return NULL;
        }
        rcvlen += len;
    
        /* バイトオーダー変換 */
        hdr.msgcode = ntohs(hdr.msgcode);
        hdr.seqno = ntohs(hdr.seqno);
        hdr.status = (int32_t)ntohl(hdr.status);
        hdr.length = (int32_t)ntohl(hdr.length);
        total = rcvlen + hdr.length;

        /* MSGCODE指定の場合は、指定以外のメッセージなら読み飛ばす */
        if (msgcode >= 0) {
            if (hdr.msgcode != (uint16_t)msgcode) {
                LOGE("%s: invalid msg code\n", __FUNCTION__);
                rvs_set_errno(EIO);
                readskip(sock,hdr.length);
                continue;
            }
        }
        if (seqno >= 0) {
            if (hdr.seqno != seqno) {
                LOGE("%s: invalid seqno\n", __FUNCTION__);
                rvs_set_errno(EIO);
                readskip(sock,hdr.length);
                continue;
            }
        }
        break;
    }

    /* バッファ長チェック */
    switch (hdr.msgcode) {
    case RAPI_M_SENDTO:
        if (getbuf) {
            plen = SENDTOBASE;
        } else {
            plen = hdr.length + sizeof(char*);
        }
        break;
    case RAPI_M_RECVFROM_RES:
        if (getbuf) {
            plen = RECVFROMBASE;
        } else {
            plen = hdr.length + sizeof(char*);
        }
        break;
    case RAPI_M_SEND:
        if (getbuf) {
            plen = SENDBASE;
        } else {
            plen = hdr.length + sizeof(char*);
        }
        break;
    case RAPI_M_RECV_RES:
        if (getbuf) {
            plen = RECVBASE;
        } else {
            plen = hdr.length + sizeof(char*);
        }
        break;
    default:
        getbuf = NULL;   /* ユーザバッファは使用しない */
        plen = hdr.length;
        break;
    }
    plen += sizeof(rvs_api_hdr_t);

    /* 受信バッファの確保 */
    if (rbuf == NULL) {
        rbuflen = plen;
        rbuf = rvs_malloc(rbuflen);
        if (rbuf == NULL) {
            LOGE("%s: cannot allocate buffer\n", __FUNCTION__);
            rvs_set_errno(ENOMEM);
            goto recverr;
        }
        msg->baloc = 1;
    } else if (rbuflen < plen) {
        LOGE("%s: cannot allocate buffer\n", __FUNCTION__);
        rvs_set_errno(EMSGSIZE);
        goto recverr;
    }

    /* メッセージヘッダのコピー */
    memcpy (rbuf, &hdr, sizeof(hdr));
    msg->header = (rvs_api_hdr_t*)rbuf;
    cur = rbuf + sizeof(rvs_api_hdr_t);

    /* パラメータ読み込み */
    while (rcvlen < total) {
        rvs_api_tlv_t* tlv;

        /* パラメータヘッダ */
        len = read(sock, cur, sizeof(rvs_api_tlv_t));
        if (len < sizeof(rvs_api_tlv_t)) {
            LOGE("%s: cannot parameter: %s\n", __FUNCTION__, strerror(errno));
            rvs_set_errno(errno);
            goto recverr;
        }
        tlv = (rvs_api_tlv_t*)cur;
        cur += len; rcvlen += len;

        /* バイトオーダー変換 */
        tlv->Type = ntohs(tlv->Type);
        tlv->Length = ntohs(tlv->Length);
        //LOGD("%s: next param=0x%x(len=%d)\n", __FUNCTION__, tlv->Type, tlv->Length); 

        /* パラメータ値の読み込み */
        if (getbuf && (tlv->Type == RAPI_P_DATA)) {
            /* ユーザバッファへの読み込み */
            int ubuflen = tlv->Length;
            char* ubuf = (*getbuf)(&ubuflen, param);
            LOGD("%s: user buffer=%p(len=%d)\n", __FUNCTION__, ubuf, ubuflen);
            if (ubuflen > tlv->Length) {
                ubuflen = tlv->Length;
            }
            len = read(sock, ubuf, ubuflen);
            if (len < ubuflen) {
                LOGE("%s: read user data : %s\n", __FUNCTION__, strerror(errno));
                rvs_set_errno(errno);
                goto recverr;
            }
            /* ユーザバッファが不足していたときは残りを読み飛ばす */
            while (len < tlv->Length) {
                char fbuf[256];
                int nlen = tlv->Length - len;
                if (nlen > 256) {
                    nlen = 256;
                }
                LOGD("%s: skip(len=%d)\n", __FUNCTION__, nlen);
                nlen = read(sock, fbuf, nlen);
                if (nlen <= 0) {
                    LOGE("%s: read user data : %s\n", __FUNCTION__, strerror(errno));
                    rvs_set_errno(errno);
                    goto recverr;
                }
                len += nlen;
            }
            /* Paddingデータの読み飛ばし */
            if (tlv->Length % 4) {
                char fbuf[4];
                int nlen = read(sock, fbuf, (4 - (tlv->Length%4)));
                if (nlen <= 0) {
                    LOGE("%s: read user data : %s\n", __FUNCTION__, strerror(errno));
                    rvs_set_errno(errno);
                    goto recverr;
                }
                len += nlen;
            }
            /* バッファポインタと実行読み込み長の設定 */
            ((rvs_api_ubuf_t*)tlv)->Buffer = ubuf;
            tlv->Length = ubuflen;
            cur += sizeof(char*);
        } else {
            /* Dataタイプの場合はポインタを設定 */
            if (tlv->Type == RAPI_P_DATA) {
                /* 読み出し位置をずらし、ここにはポインタを設定する */
                cur += sizeof(char*);
                ((rvs_api_ubuf_t*)tlv)->Buffer = cur;
            }
            /* 受信バッファ内に読み込む */
            len = read(sock, cur, tlv->Length);
            if (len < tlv->Length) {
                LOGE("%s: read param : %s\n", __FUNCTION__, strerror(errno));
                rvs_set_errno(errno);
                goto recverr;
            }
            cur += len;
            /* Paddingデータの読み飛ばし */
            if (tlv->Length % sizeof(uint32_t)) {
                int nlen = sizeof(uint32_t)-(tlv->Length%sizeof(uint32_t));
                nlen = read(sock, cur, nlen);
                if (nlen <= 0) {
                    LOGE("%s: read user data : %s\n", __FUNCTION__, strerror(errno));
                    rvs_set_errno(errno);
                    goto recverr;
                }
                cur += nlen; len += nlen;
            }
        }
        rcvlen += len;

        /* パラメータタイプのチェック */
        switch (tlv->Type) {
        case RAPI_P_SOCKET:         /* rSocket */
            if ((msg->rsock = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_ERRNO:          /* ErrorNo */
            if ((msg->rerr = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_DATA:           /* Data */
            msg->data = (rvs_api_ubuf_t*)tlv;
            break;
        case RAPI_P_FLAGS:          /* Flags */
            if ((msg->flags = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_TIMEOUT:        /* Timeout */
            if ((msg->timeout = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_LEVEL:          /* Level */
            if ((msg->level = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_OPTION:         /* Option */
            if ((msg->option = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_VALUE:          /* Value */
            msg->value = (rvs_api_str_t*)tlv;
            break;
        case RAPI_P_DOMAIN:         /* Domain */
            if ((msg->domain = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_TYPE:           /* SockType */
            if ((msg->type = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_PROTOCOL:       /* Protocol */
            if ((msg->proto = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_BACKLOG:        /* BackLog */
            if ((msg->backlog = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_HOW:           /* How */
            if ((msg->how = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_NODE:           /* Node */
            msg->node = (rvs_api_str_t*)tlv;
            break;
        case RAPI_P_SERVICE:        /* Service */
            msg->serv = (rvs_api_str_t*)tlv;
            break;
        case RAPI_P_USERID:        /* Service */
            msg->userid = (rvs_api_str_t*)tlv;
            break;
        case RAPI_P_VIFNO:        /* Service */
            if ((msg->vifno = get_int_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_SOCKEVENT:      /* SockEvent */
            if ((msg->sevent = get_sev_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_ADDRV4:         /* Addr(IPv4) */
            if ((msg->addrv4 = get_av4_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_DADDRV4:        /* Dest Addr(IPv4) */
            if ((msg->daddrv4 = get_av4_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_ADDRV6:         /* Addr(IPv6) */
            if ((msg->addrv6 = get_av6_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_DADDRV6:        /* Dest Addr(IPv6) */
            if ((msg->daddrv6 = get_av6_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_ADDRINFO:       /* AddrList */
            if ((msg->ainfo = get_ai_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_ADDRLIST:       /* AddrList */
            if ((msg->alist = get_ail_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_SEVENTLIST:  /* SockEventList */
            if ((msg->selist = get_sel_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_STATINFO:  /* StatusInfo */
            if ((msg->statinfo = get_status_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        case RAPI_P_ERRINFO:  /* ErrorInfo */
            if ((msg->errinfo = get_error_param(tlv)) == NULL) {
                goto recverr;
            }
            break;
        }
    }
    //LOGD("%s: receive msg[0x%04x,seq:%d,stat:%d](sock=%d)\n", __FUNCTION__,
    //                   hdr.msgcode, hdr.seqno, hdr.status, sock);

    return msg;

recverr:
    if (rvs_errno == 0) {
        rvs_set_errno(errno);
    }
    rvs_free_msg(msg);
    return NULL;
}

/*
 * rvs_send_msg - メッセージ送信
 *
 *     sock : 送信ソケット(SOCK_STREAM型であること)
 *     msg  : メッセージ構造体格納バッファ
 *
 *   戻り値
 *     成功時は実装に送信したメッセージ長(>0)。エラーが発生した場合は-1。
 *     rvs_errnoにエラー番号を設定する。rvs_errno = RVSA_EIOのときは、
 *     この関数から戻った後、ソケットをいったんクローズする。
 */
int rvs_send_msg (int sock, rvs_api_send_t* msg)
{
    int len, sndlen = 0;
    rvs_api_tlv_t* next;
    rvs_api_hdr_t* hdr = &msg->header;

    rvs_set_errno(0);

    /* ヘッダ部分の変換と */
    hdr->msgcode = htons(hdr->msgcode);
    hdr->seqno = htons(hdr->seqno);
    hdr->status = (int32_t)htonl(hdr->status);
    hdr->length = (int32_t)htonl(hdr->length);

    next = (rvs_api_tlv_t*)msg->buffer;

    while (next != msg->next) {
        rvs_api_tlv_t* tlv = next;
        int nlen = tlv->Length;

        /* パラメータタイプにより変換して送信 */
        switch (tlv->Type) {
        case RAPI_P_SOCKET:         /* rSocket */
        case RAPI_P_ERRNO:          /* ErrorNo */
        case RAPI_P_FLAGS:          /* Flags */
        case RAPI_P_TIMEOUT:        /* Timeout */
        case RAPI_P_LEVEL:          /* Level */
        case RAPI_P_OPTION:         /* Option */
        case RAPI_P_DOMAIN:         /* Domain */
        case RAPI_P_TYPE:           /* SockType */
        case RAPI_P_PROTOCOL:       /* Protocol */
        case RAPI_P_BACKLOG:        /* BackLog */
        case RAPI_P_VIFNO:          /* VIF No */
            if (set_int_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        case RAPI_P_DATA:           /* Data */
            nlen = sizeof(char*);
            break;
        case RAPI_P_VALUE:          /* Value */
        case RAPI_P_NODE:           /* Node */
        case RAPI_P_SERVICE:        /* Service */
        case RAPI_P_USERID:         /* UserID */
            break;
        case RAPI_P_SOCKEVENT:      /* SockEvent */
            if (set_sev_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        case RAPI_P_ADDRV4:         /* Addr(IPv4) */
        case RAPI_P_DADDRV4:        /* Dest Addr(IPv4) */
            if (set_av4_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        case RAPI_P_ADDRV6:         /* Addr(IPv6) */
        case RAPI_P_DADDRV6:        /* Dest Addr(IPv6) */
            if (set_av6_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        case RAPI_P_ADDRINFO:       /* AddrList */
            if (set_ai_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        case RAPI_P_ADDRLIST:       /* AddrList */
            if (set_ail_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        case RAPI_P_SEVENTLIST:  /* SockEventList */
            if (set_sel_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        case RAPI_P_STATINFO:  /* StatusInfo */
            if (set_status_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        case RAPI_P_ERRINFO:  /* ErrorInfo */
            if (set_error_param(tlv) == NULL) {
                goto senderr;
            }
            break;
        }

        next = (rvs_api_tlv_t*)((char*)tlv->Value + nlen);
    }

    /* ヘッダ部の送信 */
    len = write (sock, (char*)hdr, sizeof(rvs_api_hdr_t));
    if (len < sizeof(rvs_api_hdr_t)) {
        LOGE("%s: write error : %s\n", __FUNCTION__, strerror(errno));
        rvs_set_errno(RVSA_EIO);
        goto senderr;
    }
    sndlen = len;

    /* パラメータ領域の送信 */
    next = (rvs_api_tlv_t*)msg->buffer;

    while (next != msg->next) {
        rvs_api_tlv_t* tlv = next;
        int nlen = tlv->Length;

        tlv->Type = htons(tlv->Type);
        tlv->Length = htons(tlv->Length);

        if (tlv->Type == htons(RAPI_P_DATA)) {
            char pad[3] = { 0, 0, 0 };

            /* TypeとLengthだけ先に送信する */
            len = write (sock, (char*)tlv, sizeof(rvs_api_tlv_t));
            if (len < sizeof(rvs_api_tlv_t)) {
                LOGE("%s: write error : %s\n", __FUNCTION__, strerror(errno));
                rvs_set_errno(RVSA_EIO);
                goto senderr;
            }
            sndlen += len;
            /* 指定バッファから直接送る */
            len = write (sock, ((rvs_api_ubuf_t*)tlv)->Buffer, nlen);
            if (len < nlen) {
                LOGE("%s: write error : %s\n", __FUNCTION__, strerror(errno));
                rvs_set_errno(RVSA_EIO);
                goto senderr;
            }
            sndlen += len;

            /* Paddingでーたの送信 */
            if (nlen % sizeof(uint32_t)) {
                nlen = sizeof(uint32_t) - (nlen % sizeof(uint32_t));
                len = write (sock, pad, nlen);
                if (len < nlen) {
                    LOGE("%s: write error : %s\n", __FUNCTION__, strerror(errno));
                    rvs_set_errno(RVSA_EIO);
                    goto senderr;
                }
                sndlen += len;
            }

            nlen = sizeof(rvs_api_ubuf_t);

        } else {
            /* パラメータ値まで送信する */
            if (nlen % sizeof(uint32_t)) {
                nlen += sizeof(uint32_t) - (nlen % sizeof(uint32_t));
            }
            nlen += sizeof(rvs_api_tlv_t);
            len = write (sock, (char*)tlv, nlen);
            if (len < nlen) {
                LOGE("%s: write error : %s\n", __FUNCTION__, strerror(errno));
                rvs_set_errno(RVSA_EIO);
                goto senderr;
            }
            sndlen += len;
        }

        next = (rvs_api_tlv_t*)((char*)next + nlen);
    }

    //LOGD("%s: end of send msg[0x%04x,seq:%d](sock=%d)\n", __FUNCTION__,
    //                ntohs(hdr->msgcode), ntohs(hdr->seqno), sock);

    return sndlen;

senderr:
    if (rvs_errno == 0) {
        rvs_set_errno(errno);
    }
    /* 送信に失敗した場合はソケットをcloseした方がよい */
    /* ただし、close処理は上位に任せる */
    return -1;
}


/*
 * rvs_make_msg - メッセージ作成
 *
 *     msgcode : メッセージコード
 *     seqno : シーケンス番号(-1のときは内部で設定)
 *     status : ステータス
 *
 *   戻り値
 *     正常時は、作成したメッセージ構造体へのポインタ。
 *     この領域はヒープから確保するため、rvs_free()で解放する必要がある。
 *     エラー発生時はNULLで、rvs_errnoにエラーを設定する。
 */
rvs_api_send_t* rvs_make_msg (int msgcode, int seqno, int status)
{
    static int next_seq=0;
    rvs_api_send_t* msg;

    /* メッセージ構造体領域の確保 */
    msg = rvs_malloc(sizeof(rvs_api_send_t)+RVS_SBUF_BLOCK);
    if (msg == NULL) {
        rvs_set_errno(ENOMEM);
        return NULL;
    }
    memset (msg, 0, sizeof(rvs_api_send_t)+RVS_SBUF_BLOCK);
    msg->size = RVS_SBUF_BLOCK;

    /* ヘッダの設定 */
    msg->header.magic = RVSA_MAGIC;
    msg->header.msgcode = msgcode;
    if (seqno >= 0) {
        msg->header.seqno = seqno;
    } else {
        msg->header.seqno = next_seq++;
    }
    msg->header.status = status;
    msg->header.length = 0;

    /* パラメータポインタの初期化 */
    msg->next = (rvs_api_tlv_t*)msg->buffer;

    return msg;
}

static rvs_api_tlv_t* add_next_param (rvs_api_send_t* msg, int type, int length)
{
    rvs_api_tlv_t* next = msg->next;
    int elen = length;

    if (length % sizeof(uint32_t)) {
        elen += (sizeof(uint32_t) - (length % sizeof(uint32_t)));
    }

    /* バッファのサイズが不足する場合は、取り直す */
    if ((msg->size - msg->header.length) < length) {
        int len;
        /* 拡張サイズの計算 */
        if (elen > RVS_SBUF_BLOCK) {
            len = elen;
        } else {
            len = RVS_SBUF_BLOCK;
        }
        msg = rvs_realloc(msg, sizeof(rvs_api_send_t)+msg->size+len);
        if ( msg == NULL) {
            rvs_set_errno(ENOMEM);
            LOGE("%s: cannot allocate param.\n", __FUNCTION__);
            return NULL;
        }
        memset (&(msg->buffer[msg->size]), 0, len);
        msg->size = len;
    }

    /* パラメータヘッダを設定する */
    next->Type = type;

    /* メッセージ長の設定 */
    msg->header.length += elen;
    msg->next = (rvs_api_tlv_t*)((char*)next + elen);

    return next;
}

/*
 * rvs_add_int - 整数型パラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     type : パラメータタイプ
 *     val : パラメータ値
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_int (rvs_api_send_t* msg, int type, int val)
{
    rvs_api_int_t* intp = 
       (rvs_api_int_t*)add_next_param(msg, type, sizeof(rvs_api_int_t));

    if (intp == NULL ) {
        return -1;
    }

    intp->Length = sizeof(int32_t);
    intp->Integer = val;
    return sizeof(rvs_api_int_t);
}

/*
 * rvs_add_data - Dataパラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     buf : データ格納バッファ
 *     buflen : バッファに格納されたデータ長
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_data (rvs_api_send_t* msg, const char* buf, int buflen)
{
    rvs_api_ubuf_t* datap =
        (rvs_api_ubuf_t*)add_next_param(msg, RAPI_P_DATA, sizeof(rvs_api_ubuf_t));
    int elen = buflen;

    if (datap == NULL) {
        return -1;
    }

    datap->Length = buflen;
    datap->Buffer = buf;
    if (buflen%sizeof(uint32_t)) {
        elen += (sizeof(uint32_t)-(buflen%sizeof(uint32_t)));
    }
    msg->header.length += elen - sizeof(char*);

    return sizeof(rvs_api_ubuf_t);
}

/*
 * rvs_add_void - 可変長パラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     type : パラメータタイプ
 *     buf : データ格納バッファ
 *     buflen : バッファに格納されたデータ長
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_void (rvs_api_send_t* msg, int type, const char* buf, int buflen)
{
    rvs_api_str_t* datap =
        (rvs_api_str_t*)add_next_param(msg, type, sizeof(rvs_api_str_t)+buflen);

    if (datap == NULL) {
        return -1;
    }

    datap->Length = buflen;
    memcpy (datap->String, buf, buflen);
    return (sizeof(rvs_api_str_t)+buflen);
}

/*
 * rvs_add_sevent - SockEventパラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     pfd : 監視ソケットとイベントの指定
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_sevent (rvs_api_send_t* msg, struct pollfd *pfd)
{
    rvs_api_sev_t* sevp =
        (rvs_api_sev_t*)add_next_param(msg, RAPI_P_SOCKEVENT, sizeof(rvs_api_sev_t));

    if (sevp == NULL) {
        return -1;
    }

    sevp->Length = sizeof(rvs_api_sev_t) - sizeof(rvs_api_tlv_t);
    sevp->rSocket = pfd->fd;
    sevp->ReqEvents = pfd->events;
    sevp->Events = pfd->revents;
    return (sizeof(rvs_api_sev_t));
}

/*
 * rvs_add_selist - SockEventListパラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     pfds : 監視ソケットとイベントの指定
 *     nfds : 監視するイベントの数
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_selist (rvs_api_send_t* msg, struct pollfd *pfds, int nfds)
{
    int length=0;
    int i;

    /* リストのヘッダ部分 */
    rvs_api_sel_t* selist =
        (rvs_api_sel_t*)add_next_param(msg, RAPI_P_SEVENTLIST, sizeof(rvs_api_tlv_t));

    if (selist == NULL) {
        return -1;
    }

    /* SockEvent構造体の要素を１つずつ追加する */
    for (i=0; i<nfds; i++, pfds++) {
        int len = rvs_add_sevent(msg, pfds);
        if (len < 0) {
            return -1;
        }
        length += len;
    }

    selist->Length = length;

    return (sizeof(rvs_api_tlv_t)+length);
}

/*
 * rvs_add_fdsets - SockEventListパラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     nfds : 監視するソケットの最大値
 *     readfds : 受信イベントを待つFDのセット
 *     writefds : 送信イベントを待つFDのセット
 *     exceptfds : 例外イベントを待つFDのセット
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_fdsets (rvs_api_send_t* msg, int nfds,
            fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
{
    int length=0;
    int i, nevs=0;
    struct pollfd pfd;

    /* リストのヘッダ部分 */
    rvs_api_sel_t* selist =
        (rvs_api_sel_t*)add_next_param(msg, RAPI_P_SEVENTLIST, sizeof(rvs_api_tlv_t));

    if (selist == NULL) {
        return -1;
    }

    /* SockEvent構造体の要素を１つずつ追加する */
    memset(&pfd,0,sizeof(pfd));
    for (i=0; i<nfds; i++) {
        short events = 0;

        if (readfds && FD_ISSET(i,readfds)) {
            events |= POLLIN;
        }
        if (writefds && FD_ISSET(i,writefds)) {
            events |= POLLOUT;
        }
        if (exceptfds && FD_ISSET(i,exceptfds)) {
            events |= POLLERR;
        }
        if (events == 0) continue;

#ifdef RSI_SOCKBASE
        pfd.revents = events;
        LOGD("%s:[SOCKBASE] pfd.revents(sock=%d) ==> 0x%x\n",
                   __FUNCTION__, i, events);
#else
        pfd.events = events;
        LOGD("%s: pfd.events(sock=%d) ==> 0x%x\n",
                   __FUNCTION__, i, events);
#endif
        pfd.fd = i;
        int len = rvs_add_sevent(msg, &pfd);
        if (len < 0) {
            return -1;
        }
        length += len;
        nevs++;
#ifdef RSI_SOCKBASE
        pfd.revents = 0;
#else
        pfd.events = 0;
#endif
    }

    msg->header.status = nevs;
    selist->Length = length;

    return (sizeof(rvs_api_tlv_t)+length);
}


/*
 * rvs_add_addrv4  - AddrV4パラメータの追加
 * rvs_add_daddrv4 - Dest AddrV4パラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     addr : アドレス情報
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_addrv4 (rvs_api_send_t* msg, const struct sockaddr_in *addr)
{
    rvs_api_av4_t* av4 =
        (rvs_api_av4_t*)add_next_param(msg, RAPI_P_ADDRV4, sizeof(rvs_api_av4_t));

    if (av4 == NULL) {
        return -1;
    }

    av4->Length = sizeof(rvs_api_av4_t) - sizeof(rvs_api_tlv_t);
    av4->Reserved = 0;
    av4->PortNo = addr->sin_port;
    av4->IPAddress = addr->sin_addr.s_addr;
    return (sizeof(rvs_api_av4_t));
}
int rvs_add_daddrv4 (rvs_api_send_t* msg, const struct sockaddr_in *addr)
{
    rvs_api_av4_t* av4 =
        (rvs_api_av4_t*)add_next_param(msg, RAPI_P_DADDRV4, sizeof(rvs_api_av4_t));

    if (av4 == NULL) {
        return -1;
    }

    av4->Length = sizeof(rvs_api_av4_t) - sizeof(rvs_api_tlv_t);
    av4->Reserved = 0;
    av4->PortNo = addr->sin_port;
    av4->IPAddress = addr->sin_addr.s_addr;
    return (sizeof(rvs_api_av4_t));
}

/*
 * rvs_add_addrv6  - AddrV6パラメータの追加
 * rvs_add_daddrv6 - Dest AddrV6パラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     addr : アドレス情報
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_addrv6 (rvs_api_send_t* msg, const struct sockaddr_in6 *addr)
{
    rvs_api_av6_t* av6 =
        (rvs_api_av6_t*)add_next_param(msg, RAPI_P_ADDRV6, sizeof(rvs_api_av6_t));

    if (av6 == NULL) {
        return -1;
    }

    av6->Length = sizeof(rvs_api_av6_t) - sizeof(rvs_api_tlv_t);
    av6->Reserved = 0;
    av6->PortNo = addr->sin6_port;
    av6->FlowInfo = addr->sin6_flowinfo;
    memcpy (&av6->Address, &addr->sin6_addr, sizeof(struct in6_addr));
    av6->ScopeID = addr->sin6_scope_id;
    return (sizeof(rvs_api_av6_t));
}
int rvs_add_daddrv6 (rvs_api_send_t* msg, const struct sockaddr_in6 *addr)
{
    rvs_api_av6_t* av6 =
        (rvs_api_av6_t*)add_next_param(msg, RAPI_P_DADDRV6, sizeof(rvs_api_av6_t));

    if (av6 == NULL) {
        return -1;
    }

    av6->Length = sizeof(rvs_api_av6_t) - sizeof(rvs_api_tlv_t);
    av6->Reserved = 0;
    av6->PortNo = addr->sin6_port;
    av6->FlowInfo = addr->sin6_flowinfo;
    memcpy (&av6->Address, &addr->sin6_addr, sizeof(struct in6_addr));
    av6->ScopeID = addr->sin6_scope_id;
    return (sizeof(rvs_api_av6_t));
}

/*
 * rvs_add_addr  - Addrressパラメータの追加
 * rvs_add_daddr - Dest Addrressパラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     addr : アドレス情報
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_addr (rvs_api_send_t* msg, const struct sockaddr *addr)
{
    if (addr->sa_family == AF_INET) {
        return rvs_add_addrv4(msg, (struct sockaddr_in*)addr);
    } else if (addr->sa_family == AF_INET6) {
        return rvs_add_addrv6(msg, (struct sockaddr_in6*)addr);
    } else {
        rvs_set_errno(EINVAL);
        return -1;
    }
}
int rvs_add_daddr (rvs_api_send_t* msg, const struct sockaddr *addr)
{
    if (addr->sa_family == AF_INET) {
        return rvs_add_daddrv4(msg, (struct sockaddr_in*)addr);
    } else if (addr->sa_family == AF_INET6) {
        return rvs_add_daddrv6(msg, (struct sockaddr_in6*)addr);
    } else {
        rvs_set_errno(EINVAL);
        return -1;
    }
}

/*
 * rvs_add_statinfo - ステータス情報パラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     statusp : ステータス情報格納領域
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_statinfo (rvs_api_send_t* msg, const rvs_status_t* statusp)
{
    int i;
    rvs_api_status_t* stat =
        (rvs_api_status_t*)add_next_param(msg, RAPI_P_STATINFO, sizeof(rvs_api_status_t));

    if (stat == NULL) {
        return -1;
    }

    stat->VPNStat = statusp->vpnstat;
    stat->P2PCount = statusp->p2pcon;
    stat->Length =  sizeof(uint32_t);

    for (i=0; i<stat->P2PCount; i++) {
        int length = strlen(statusp->remotename[i]);
        int elen = length;

        if (length % sizeof(uint32_t)) {
            elen += sizeof(uint32_t) - (length % sizeof(uint32_t));
        }
        rvs_api_str_t* userid =
           (rvs_api_str_t*)add_next_param(msg, RAPI_P_USERID, sizeof(rvs_api_str_t)+elen);
        strncpy (userid->String, statusp->remotename[i], length);
        userid->Length = length;

        stat->Length += sizeof(rvs_api_str_t) + elen;
    }

    return (stat->Length+sizeof(rvs_api_tlv_t));
}

/*
 * rvs_add_errinfo - エラー情報パラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     errorp : エラー情報格納領域
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_errinfo (rvs_api_send_t* msg, const rvs_error_t* errorp)
{
    rvs_api_error_t* errp =
        (rvs_api_error_t*)add_next_param(msg, RAPI_P_ERRINFO, sizeof(rvs_api_error_t));

    if (errp == NULL) {
        return -1;
    }

    errp->RequestType = errorp->rtype;
    errp->ReasonType = errorp->reason_type;
    memcpy (&errp->ErrCode, &errorp->reason, sizeof(errp->ErrCode));
    errp->Length =  sizeof(uint32_t) + sizeof(errp->ErrCode);

    if (errorp->remote) {
        int length = strlen(errorp->remote);
        if (length > 0) {
            int elen = length;
            if (length % sizeof(uint32_t)) {
                elen += sizeof(uint32_t) - (length % sizeof(uint32_t));
            }

            rvs_api_str_t* userid =
               (rvs_api_str_t*)add_next_param(msg, RAPI_P_USERID, sizeof(rvs_api_str_t)+elen);
            strncpy (userid->String, errorp->remote, length);
            userid->Length = length;

            errp->Length += sizeof(rvs_api_str_t) + elen;
        }
    }

    return (errp->Length+sizeof(rvs_api_tlv_t));
}

/*
 * rvs_add_ainfo - AddrInfoパラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     ai : アドレス情報
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_ainfo (rvs_api_send_t* msg, struct addrinfo *ai)
{
    rvs_set_errno(EOPNOTSUPP);
    return -1;
}

/*
 * rvs_add_alist - AddrListパラメータの追加
 *
 *     msg : 追加するメッセージ構造体
 *     al : アドレス情報リスト
 *
 *   戻り値
 *     正常時はパラメータ構造体長。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_add_alist (rvs_api_send_t* msg, struct addrinfo *al)
{
    rvs_set_errno(EOPNOTSUPP);
    return -1;
}

/*
 * rvs_get_av4 - AddressV4パラメータの取得
 *
 *     msg : 取得もとの受信メッセージ構造体
 *     addr : アドレス格納領域
 *     addrlen : addr領域長
 *
 *   戻り値
 *     正常時は実際に格納した長さ
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_get_av4 (rvs_api_msg_t* msg, struct sockaddr_in *addr, int addrlen)
{
    if (addrlen < sizeof(struct sockaddr_in)) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    /* アドレス構造体の設定 */
    addr->sin_family = AF_INET;
    addr->sin_port = msg->addrv4->PortNo;
    addr->sin_addr.s_addr = msg->addrv4->IPAddress;

LOGD("%s: Set address to %p\n", __FUNCTION__, addr);
    return sizeof(struct sockaddr_in);
}
int rvs_get_dav4 (rvs_api_msg_t* msg, struct sockaddr_in *addr, int addrlen)
{
    if (addrlen < sizeof(struct sockaddr_in)) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    /* アドレス構造体の設定 */
    addr->sin_family = AF_INET;
    addr->sin_port = msg->daddrv4->PortNo;
    addr->sin_addr.s_addr = msg->daddrv4->IPAddress;

    return sizeof(struct sockaddr_in);
}

/*
 * rvs_get_av6  - AddressV6パラメータの取得
 * rvs_get_dav6 - Dest AddressV6パラメータの取得
 *
 *     msg : 取得もとの受信メッセージ構造体
 *     addr : アドレス格納領域
 *     addrlen : addr領域長
 *
 *   戻り値
 *     正常時は実際に格納した長さ
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_get_av6 (rvs_api_msg_t* msg, struct sockaddr_in6 *addr, int addrlen)
{
    if (addrlen < sizeof(struct sockaddr_in6)) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    /* アドレス構造体の設定 */
    addr->sin6_family = AF_INET;
    addr->sin6_port = msg->addrv6->PortNo;
    addr->sin6_flowinfo = msg->addrv6->FlowInfo;
    addr->sin6_scope_id = msg->addrv6->ScopeID;
    memcpy (&(addr->sin6_addr), &(msg->addrv6->Address), sizeof(struct in6_addr));

    return sizeof(struct sockaddr_in6);
}
int rvs_get_dav6 (rvs_api_msg_t* msg, struct sockaddr_in6 *addr, int addrlen)
{
    if (addrlen < sizeof(struct sockaddr_in6)) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    /* アドレス構造体の設定 */
    addr->sin6_family = AF_INET;
    addr->sin6_port = msg->daddrv6->PortNo;
    addr->sin6_flowinfo = msg->daddrv6->FlowInfo;
    addr->sin6_scope_id = msg->daddrv6->ScopeID;
    memcpy (&(addr->sin6_addr), &(msg->daddrv6->Address), sizeof(struct in6_addr));

    return sizeof(struct sockaddr_in6);
}

/*
 * rvs_get_addr  - Addressパラメータの取得
 * rvs_get_daddr - Dest Addressパラメータの取得
 *
 *     msg : 取得もとの受信メッセージ構造体
 *     addr : アドレス格納領域
 *     addrlen : addr領域長
 *
 *   戻り値
 *     正常時は実際に格納した長さ
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_get_addr (rvs_api_msg_t* msg, struct sockaddr *addr, int addrlen)
{
    if (addr == NULL) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    if (msg->addrv4) {
        return rvs_get_av4(msg, (struct sockaddr_in*)addr, addrlen);
    } else if (msg->addrv6) {
        return rvs_get_av6(msg, (struct sockaddr_in6*)addr, addrlen);
    } else {
        rvs_set_errno(EIO);
        return -1;
    }
}
int rvs_get_daddr (rvs_api_msg_t* msg, struct sockaddr *addr, int addrlen)
{
    if (addr == NULL) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    if (msg->daddrv4) {
        return rvs_get_dav4(msg, (struct sockaddr_in*)addr, addrlen);
    } else if (msg->daddrv6) {
        return rvs_get_dav6(msg, (struct sockaddr_in6*)addr, addrlen);
    } else {
        rvs_set_errno(EIO);
        return -1;
    }
}


/*
 * rvs_get_fdsets - イベント発生FD情報の取得
 *
 *     msg : チェックするメッセージ構造体
 *     readfds : 受信イベントを待つFDのセット
 *     writefds : 送信イベントを待つFDのセット
 *     exceptfds : 例外イベントを待つFDのセット
 *
 *   戻り値
 *     正常時は発生イベント数。
 *     エラー時は-1でrvs_errnoにエラー番号を設定する。
 */
int rvs_get_fdsets (rvs_api_msg_t* msg,
            fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
{
    rvs_api_sel_t* selist = msg->selist;
    int nevs, i, ret=0;
#ifdef RSI_SOCKBASE
    int nfds=0;
#endif

    /* リストのヘッダ部分 */
    if (selist == NULL || msg->header->status < 0) {
        return -1;
    }

    /* SockEvent構造体の要素を１つずつチェックする */
    nevs = msg->header->status;
    if (readfds) FD_ZERO(readfds);
    if (writefds) FD_ZERO(writefds);
    if (exceptfds) FD_ZERO(exceptfds);

    for (i=0; i < nevs; i++) {
        int sock = selist->SockEvent[i].rSocket;
        uint16_t events;

#ifdef RSI_SOCKBASE
        events = selist->SockEvent[i].ReqEvents;
        LOGD("%s:[SOCKBASE] socket %d ReqEvents = 0x%x\n", __FUNCTION__,
              sock, events);
#else
        events = selist->SockEvent[i].Events;
        LOGD("%s: socket %d Events = 0x%x\n", __FUNCTION__,
              sock, events);
#endif

        if (events == 0) {
            continue;
        }

#ifdef RSI_SOCKBASE
        if (sock >= nfds) {
            nfds = sock+1;
            LOGD("%s:[SOCKBASE] nfds ==> %d\n", __FUNCTION__, nfds);
        }
#endif

        if ( readfds && (events & POLLIN) ) {
            FD_SET(sock, readfds);
            ret++;
        }
        if ( writefds && (events & POLLOUT) ) {
            FD_SET(sock, writefds);
            ret++;
        }
        if ( exceptfds && (events & (POLLERR|POLLHUP)) ) {
            FD_SET(sock, exceptfds);
            ret++;
        }
    }

#ifdef RSI_SOCKBASE
    return nfds;
#else
    return ret;
#endif
}


